require 'depac-common/softlayer'
require 'depac-deployment/environment_configuration'
require 'depac-deployment/helper'
require 'depac-deployment/configure'
require 'depac-deployment/provision'
require 'depac-deployment/update_ihsplugin'
require 'depac-common/constants'
require 'pp'

# Adds instances specified in inputConfigObject to an existing environment
def addInstance(existingEnvConfigObject, inputConfigObject, buildLabel)
	# get build label
	if(buildLabel == nil)
		buildLabel = existingEnvConfigObject.getBuildLabel()
	end
	# get environment name
	envName = existingEnvConfigObject.getEnvironmentName()
	
	# provision instance based on the input configuration
	nodeInfoMap = provisionInstance(inputConfigObject, buildLabel, envName, 0, existingEnvConfigObject)
	updateOutputWithNodeInformation(inputConfigObject, nodeInfoMap)
	
	#Order NimSoft Advanced Monitor, if configured nimsoft in price-deploy.yml
    if inputConfigObject.getEnvironmentConfiguration()['nimsoftConfig'] !=nil
       $slmgr.oderADMornitor(nodeInfoMap, inputConfigObject.getEnvironmentConfiguration())
    end
	
	# the ip addresses and info populated in this map will be used for configuring
	nodeInfoParamMap = buildNodeInfoParamMap(existingEnvConfigObject)
	
	# configure instance
	configureInstance(nodeInfoMap, nodeInfoParamMap, existingEnvConfigObject.getEnvironmentConfiguration())	
	
	# configure newrelic application name
	configureNRAppName(nodeInfoMap, existingEnvConfigObject.getEnvironmentConfiguration(), "add")     
	
	# update IHS plugin configure
	updateIHSPlugin_internal(nodeInfoMap, Depac::CloudDeploymentConstants::CLD_DPL_KEYPATH, inputConfigObject.getEnvironmentConfiguration(), "add")
	
	# update 'existingEnvConfigObject' with the infomation of the newly added/provisioned instances
	outputConfigObject = updateOutputConfigObject(existingEnvConfigObject, inputConfigObject)
	
	return outputConfigObject
end

# Return the database node info by type - authoring or runtime
def getDatabaseNodeInfo(envConfigObject, type)
	dbConfig = envConfigObject.getDatabaseConfigurationByType(type)
	
	if(dbConfig != nil)
		return dbConfig[Depac::CloudDeploymentConstants::NODE_INFO]
	else
		return nil
	end
end

def updateOutputConfigObject(baseConfigObj, newConfigObj)
	newEnvConfig = newConfigObj.getEnvironmentConfiguration()

	typeArr = getEnvironmentTypes()
	
	typeArr.each do |type|
		if(newEnvConfig[type] != nil)
			newEnvConfig[type].each do |config|
				role = config[Depac::CloudDeploymentConstants::ROLE]
				noOfNodes = 0
				
				if(role == Depac::CloudDeploymentConstants::ROLE_AGENT)
					serverNameArr = config[Depac::CloudDeploymentConstants::AGENT_NODES]
					noOfNodes = serverNameArr.length
					
					baseNodeConfig = baseConfigObj.getNodeConfigurationByRoleAndType(role, type)
					baseServerNameArr = baseNodeConfig[Depac::CloudDeploymentConstants::AGENT_NODES]
					
					serverNameArr.each do |serverName|
						baseServerNameArr.push(serverName)
					end
				elsif(role == Depac::CloudDeploymentConstants::ROLE_INTG)
					serverNameArr = config[Depac::CloudDeploymentConstants::INTG_NODES]
					noOfNodes = serverNameArr.length
					
					baseNodeConfig = baseConfigObj.getNodeConfigurationByRoleAndType(role, type)
					baseServerNameArr = baseNodeConfig[Depac::CloudDeploymentConstants::INTG_NODES]
					
					serverNameArr.each do |serverName|
						baseServerNameArr.push(serverName)
					end
				else
					noOfNodes = config[Depac::CloudDeploymentConstants::NO_OF_NODES].to_i
					
					# If no of nodes is greater than 0, update the base configuration
					if(noOfNodes > 0)
						baseNodeConfig = baseConfigObj.getNodeConfigurationByRoleAndType(role, type)
						baseNoOfNodes = baseNodeConfig[Depac::CloudDeploymentConstants::NO_OF_NODES].to_i
						
						# Update the total number of nodes
						baseNodeConfig[Depac::CloudDeploymentConstants::NO_OF_NODES] = baseNoOfNodes + noOfNodes
					end
				end
				
				# Update Node Info array if necessary
				if(noOfNodes > 0)
					# Get the node info
					baseNodeInfoArr = baseNodeConfig[Depac::CloudDeploymentConstants::NODE_INFO]
						
					# Get Node Info Array
					nodeInfoArr = config[Depac::CloudDeploymentConstants::NODE_INFO]
					
					# Update the node info
					nodeInfoArr.each do |nodeInfo|
						baseNodeInfoArr.push(nodeInfo)
					end
				end
			end
		end
	end
	return baseConfigObj
end

# Validate add instnace configuration
def validateAddInstanceConfiguration(existingEnvConfigObject, inputConfigObject)
	authoringNodes = inputConfigObject.getNodeConfigurationByType(Depac::CloudDeploymentConstants::AUTHORING_NODES)
	runtimeNodes = inputConfigObject.getNodeConfigurationByType(Depac::CloudDeploymentConstants::RUNTIME_NODES)
	sharedNodes = inputConfigObject.getNodeConfigurationByType(Depac::CloudDeploymentConstants::SHARED_NODES)
	
	dbNodeInfoAuthoring = getDatabaseNodeInfo(existingEnvConfigObject, Depac::CloudDeploymentConstants::AUTHORING_NODES)
	dbNodeInfoRuntime = getDatabaseNodeInfo(existingEnvConfigObject, Depac::CloudDeploymentConstants::RUNTIME_NODES)
	
	# validation 1 - adding authoring nodes, while db authoring node info is nil
	if(authoringNodes != nil and  dbNodeInfoAuthoring == nil)
		Depac::Log.write("ERROR", "Database node info for the authoring environment not found.")
		exit 3
	end
	
	# validation 2 - adding runtime nodes, while dn runtime node info is nil
	if(runtimeNodes != nil and  dbNodeInfoRuntime == nil)
		Depac::Log.write("ERROR", "Database node info for the runtime environment not found.")
		exit 3
	end
	
	# validation 3 - addition of database nodes
	if(inputConfigObject.getDatabaseConfigurationByType(Depac::CloudDeploymentConstants::AUTHORING_NODES) != nil or inputConfigObject.getDatabaseConfigurationByType(Depac::CloudDeploymentConstants::RUNTIME_NODES) != nil)
		Depac::Log.write("ERROR", "Addition of a database instance is not supported.")
		exit 3
	end
	
	# validation 4 - addition of jms nodes
	if(inputConfigObject.getNodeConfigurationByRoleAndType(Depac::CloudDeploymentConstants::ROLE_JMS, Depac::CloudDeploymentConstants::AUTHORING_NODES) != nil or inputConfigObject.getNodeConfigurationByRoleAndType(Depac::CloudDeploymentConstants::ROLE_JMS, Depac::CloudDeploymentConstants::RUNTIME_NODES) != nil)
		Depac::Log.write("ERROR", "Addition of a jms instance is not supported.")
		exit 3
	end
end

